package bitmap

import "sync/atomic"

type Bits = uint32

// Bitmap 标识对应的位是否存在
type Bitmap struct {
	data Bits
}

// Append 将 data 中 mask 对应的位设置为 1
func (bf *Bitmap) Append(mask Bits) {
	for {
		old := atomic.LoadUint32(&bf.data)
		oldOnes := old & mask // old 中哪些已经是 1 了
		if oldOnes == mask {  // old 中 mask 对应的已经全是 1 了
			return
		}
		due := old | mask
		if atomic.CompareAndSwapUint32(&bf.data, old, due) { // 自旋锁
			return
		}
	}
}

// Remove 将 data 中 mask 对应的位设置为 0
func (bf *Bitmap) Remove(mask Bits) {
	for {
		old := atomic.LoadUint32(&bf.data)
		oldZeros := old & mask // old 中哪些已经是 0 了
		if oldZeros == 0 {     // old 中 mask 对应的已经全是 0 了
			return
		}
		due := old ^ oldZeros // old 中被 mask 覆盖的 1 改成 0
		if atomic.CompareAndSwapUint32(&bf.data, old, due) {
			return
		}
	}
}

// HasAny 返回 data 中 mask 对应的位是否存在 1
func (bf *Bitmap) HasAny(mask Bits) bool {
	return (atomic.LoadUint32(&bf.data) & mask) != 0
}

// HasAll 返回 data 中 mask 对应的位是否全是 1
func (bf *Bitmap) HasAll(mask Bits) bool {
	return (atomic.LoadUint32(&bf.data) & mask) != mask
}

// HasOnlySpecified 返回 data 中 mask 对应的位是否恰好是 presence
func (bf *Bitmap) HasOnlySpecified(mask, presence Bits) bool {
	return (atomic.LoadUint32(&bf.data) & mask) == presence
}
